﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using QW.Core.Helper;

namespace QW.Core.File.Local
{
    /// <summary>
    /// 本地文件处理程序
    /// </summary>
    public class LocalFileHandler : IFileHandler
    {
        /// <summary>
        /// 构建
        /// </summary>
        public void Build()
        {

        }

        #region 文件
        /// <summary>
        /// 获取文件内容
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns></returns>
        public byte[] GetFileContent(string name)
        {
            FileStream fs = (FileStream)GetFileStream(name);
            byte[] byteData = new byte[fs.Length];
            fs.Read(byteData, 0, byteData.Length);
            fs.Close();
            return byteData;
        }
        /// <summary>
        /// 获取文件流
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns></returns>
        public Stream GetFileStream(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new FileNotFoundException("文件不存在");
            }
            FileStream fs = new FileStream(name, FileMode.Open);
            return fs;
        }
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="stream"></param>
        /// <param name="overwrite">是否覆盖已存在文件</param>
        public void CreateFile(string name, Stream stream, bool overwrite = false)
        {
            var fileContent = StreamToBytes(stream);
            CreateFile(name, fileContent, overwrite);
        }
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <param name="content">文件内容</param>
        /// <param name="overwrite">是否覆盖已存在文件</param>
        /// <param name="encoding">字符编码;默认 utf-8</param>
        public void CreateFile(string name, string content, bool overwrite = false, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            byte[] fileContent = encoding.GetBytes(content);
            CreateFile(name, fileContent, overwrite);
        }
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="content">文件内容</param>
        /// <param name="overwrite">是否覆盖已存在文件</param>
        public void CreateFile(string name, byte[] content, bool overwrite = false)
        {
            var dir = name.Remove(name.LastIndexOf("\\") + 1);
            CreateFolder(dir);
            if (ExistFile(name, false) && !overwrite)
            {
                throw new FileException("文件已存在");
            }
            using (FileStream fs = new FileStream(name, FileMode.Create))
            {
                fs.Write(content, 0, content.Length);
            }
        }

        /// <summary>
        /// 追加文件内容
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <param name="stream">文件流</param>
        public void AppendFile(string name, Stream stream)
        {
            var fileContent = StreamToBytes(stream);
            AppendFile(name, fileContent);
        }

        /// <summary>
        /// 追加文件内容
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <param name="content">追加内容</param>
        /// <param name="encoding">字符编码;默认 utf-8</param>
        public void AppendFile(string name, string content, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            byte[] fileContent = encoding.GetBytes(content);
            AppendFile(name, fileContent);
        }
        /// <summary>
        /// 追加文件内容
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <param name="content">追加内容</param>
        public void AppendFile(string name, byte[] content)
        {
            var path = name;
            var dir = path.Remove(path.LastIndexOf("\\"));
            CreateFolder(dir);
            using (FileStream fs = new FileStream(path, FileMode.Append))
            {
                fs.Write(content, 0, content.Length);
            }
        }
        /// <summary>
        /// 判断文件是否存在
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <param name="isRelative">是否相对路径;默认 true</param>
        /// <returns></returns>
        public bool ExistFile(string name, bool isRelative = true)
        {
            var path = name;
            if (isRelative)
            {
                path = IOHelper.GetMapPath(path);
            }
            return System.IO.File.Exists(path);
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="name">文件名称</param>
        public void DeleteFile(string name)
        {
            var path = name;
            if (ExistFile(path, false))
            {
                System.IO.File.Delete(path);
            }
        }

        /// <summary>
        /// 删除多个文件
        /// </summary>
        /// <param name="names">文件名称集合</param>
        public void DeleteFiles(List<string> names)
        {
            foreach (var item in names)
            {
                DeleteFile(item);
            }
        }
        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="source">源文件名称</param>
        /// <param name="target">目标文件名称</param>
        /// <param name="overwrite">是否允许覆盖 默认为false</param>
        public void CopyFile(string source, string target, bool overwrite = false)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                throw new FileNotFoundException("文件不存在");
            }
            var s = source;
            var d = target;
            var dir = target.Remove(target.LastIndexOf("\\"));
            CreateFolder(dir);
            if (!overwrite && ExistFile(d, false))
            {
                throw new FileException("文件已存在");
            }

            System.IO.File.Copy(s, d, overwrite);
        }

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="source">源文件名称</param>
        /// <param name="target">目标文件名称</param>
        /// <param name="overwrite">是否允许覆盖 默认为false</param>
        public void MoveFile(string source, string target, bool overwrite = false)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                throw new FileNotFoundException("文件不存在");
            }
            var s = source;
            var d = target;
            var dir = target.Remove(target.LastIndexOf("\\"));
            CreateFolder(dir);
            var has = ExistFile(d, false);
            if (!overwrite && ExistFile(d, false) && has)
            {
                throw new FileException("文件已存在");
            }
            if (has)
            {
                System.IO.File.Delete(d);
            }
            System.IO.File.Move(s, d);
        }

        /// <summary>
        /// 获取文件元信息
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns></returns>
        public FileMetaInfo GetFileMetaInfo(string name)
        {
            FileMetaInfo minfo = new FileMetaInfo();
            var file = name;
            FileInfo finfo = new FileInfo(file);
            minfo.ContentLength = finfo.Length;
            minfo.Extension = finfo.Extension;
            minfo.CreationTime = finfo.CreationTime;
            minfo.Attributes = finfo.Attributes;
            minfo.LastModifiedTime = finfo.LastWriteTime;
            minfo.LastAccessTime = finfo.LastAccessTime;
            return minfo;
        }
        #endregion

        #region 目录
        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="name">目录名称</param>
        public void CreateFolder(string name)
        {
            var dir = name;
            if (!ExistFolder(dir, false))
            {
                Directory.CreateDirectory(dir);
            }
        }
        /// <summary>
        /// 目录是否存在
        /// </summary>
        /// <param name="name">目录名称</param>
        /// <param name="isRelative">是否相对路径;默认 true</param>
        /// <returns></returns>
        public bool ExistFolder(string name, bool isRelative = true)
        {
            var path = name;
            if (isRelative)
            {
                path = IOHelper.GetMapPath(path);
            }
            var result = System.IO.Directory.Exists(path);
            return result;
        }
        /// <summary>
        /// 删除目录
        /// </summary>
        /// <param name="name">目录名称</param>
        /// <param name="recursive">是否移除子目录和文件；默认 false</param>
        public void DeleteFolder(string name, bool recursive = false)
        {
            var path = name;
            if (ExistFolder(path, false))
            {
                System.IO.Directory.Delete(path, recursive);
            }
        }
        /// <summary>
        /// 获取目录下的文件
        /// <para>不包含目录名返回</para>
        /// </summary>
        /// <param name="name">目录名称</param>
        /// <param name="isFullName">是否全路径名</param>
        /// <returns></returns>
        public List<string> GetFolderFiles(string name, bool isFullName = false)
        {
            List<string> files = new List<string>();
            var path = name;
            if (ExistFolder(path, false))
            {
                var d = new DirectoryInfo(path);
                var tmp = d.GetFiles();
                foreach (var item in tmp)
                {
                    if (isFullName)
                    {
                        files.Add(item.FullName);
                    }
                    else
                    {
                        files.Add(item.Name);
                    }
                }
            }
            return files;
        }
        /// <summary>
        /// 获取目录下的子目录
        /// <para>不包含目录名返回</para>
        /// </summary>
        /// <param name="name">目录名称</param>
        /// <param name="self">是否包含自身</param>
        /// <param name="isFullName">是否全路径名</param>
        /// <returns></returns>
        public List<string> GetFolderSubFolder(string name, bool self = false, bool isFullName = false)
        {
            List<string> dirs = new List<string>();
            var path = name;
            if (ExistFolder(path, false))
            {
                var d = new DirectoryInfo(path);
                if (self)
                {
                    if (isFullName)
                    {
                        dirs.Add(d.FullName);
                    }
                    else
                    {
                        dirs.Add(d.Name);
                    }
                }
                var tmp = d.GetDirectories();
                foreach (var item in tmp)
                {
                    if (isFullName)
                    {
                        dirs.Add(item.FullName);
                    }
                    else
                    {
                        dirs.Add(item.Name);
                    }
                }
            }
            return dirs;
        }
        /// <summary>
        /// 获取目录元信息
        /// </summary>
        /// <param name="name">目录名称</param>
        /// <returns></returns>
        public FolderMetaInfo GetFolderMetaInfo(string name)
        {
            FolderMetaInfo minfo = new FolderMetaInfo();
            var path = name;
            DirectoryInfo dinfo = new DirectoryInfo(path);
            minfo.CreationTime = dinfo.CreationTime;
            minfo.Attributes = dinfo.Attributes;
            minfo.LastModifiedTime = dinfo.LastWriteTime;
            minfo.LastAccessTime = dinfo.LastAccessTime;
            return minfo;
        }
        /// <summary>
        /// 复制目录
        /// </summary>
        /// <param name="source">源文件夹</param>
        /// <param name="target">目标文件夹</param>
        /// <param name="includeFile">是否复制文件</param>
        /// <returns></returns>
        public bool CopyFolder(string source, string target, bool includeFile)
        {
            CreateFolder(target);
            //复制文件
            if (includeFile)
            {
                foreach (string fileName in GetFolderFiles(source))
                {
                    CopyFile(IOHelper.PathCombine(source, fileName), IOHelper.PathCombine(target, fileName), true);
                }
            }
            //复制文件夹
            foreach (string subName in GetFolderSubFolder(source))
            {
                CopyFolder(IOHelper.PathCombine(source, subName), IOHelper.PathCombine(target, subName), includeFile);
            }

            return true;
        }
        /// <summary>
        /// 移动目录
        /// </summary>
        /// <param name="source">源文件夹</param>
        /// <param name="target">目标文件夹</param>
        /// <returns></returns>
        public bool MoveFolder(string source, string target)
        {
            //复制
            CopyFolder(source, target, true);
            //删除
            DeleteFolder(source, true);
            return true;
        }
        #endregion

        /// <summary>
        /// 获取远程全路径地址
        /// </summary>
        /// <returns></returns>
        public string GetRomotePath(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return "";
            }
            if (!path.StartsWith("http"))
            {
                return QW.Core.Web.Url.GetBaseUrl() + path.Trim('/');
            }
            else
            {
                return path;
            }
        }
        /// <summary>
        /// 流转数组
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }
    }
}
